﻿using System;
using System.Collections.Generic;
using System.Linq;
/*
* This file is part of WinMergeFS.
*
* WinMergeFS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.

* WinMergeFS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WinMergeFS.  If not, see <http://www.gnu.org/licenses/>.
*/

using System.Text;
using System.IO;
using RealtimeTrace;

namespace WinMergeFS.Common
{
    public class RootSelectHelper : Itraceable
    {
        #region RealtimeTrace

        /// <summary>
        /// Use this method to initialize the RealTimeTrace.
        /// This method should be called within the class constructor(s) 
        /// if you want to override the default RealtimeTrace configuration.
        /// </summary>
        private void InitializeRealTimeTrace()
        {
            this.RealTimeTraceProvider = DataProviderType.LogFile;
            this.PreferredDumpType = DumpType.XML;
        }

        private DataProviderType _RealTimeTraceProvider = DataProviderType.LogFile;
        /// <summary>
        /// Gets or Sets the Data Store provider for the RealTimeTrace.
        /// The default Data Storage provider is a raw text file.
        /// For Windows application, this raw text file is stored at the same level of the running executable.
        /// For ASP.NET application, this raw text file is stored at the same level of the aspx page.
        /// For UI Components, this raw text file is stored in the "My Documents" user folder.
        /// By default the name of the log file is *RealtimeTrace.log*
        /// </summary>
        public DataProviderType RealTimeTraceProvider
        {
            get
            {
                return this._RealTimeTraceProvider;
            }
            set
            {
                this._RealTimeTraceProvider = value;
            }
        }

        private DumpType _PreferredDumpType = DumpType.XML;
        /// <summary>
        /// Gets or Sets the type of dump for the current class.
        /// </summary>
        public DumpType PreferredDumpType
        {
            get
            {
                return this._PreferredDumpType;
            }
            set
            {
                this._PreferredDumpType = value;
            }
        }

        private bool _HasErrors = false;
        /// <summary>
        /// Checks if an error has occured within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public bool HasErrors
        {
            get { return this._HasErrors; }
            set { this._HasErrors = value; }
        }

        private System.String _LastError = System.String.Empty;
        /// <summary>
        /// Gets the last known error from the last call of a public/private member within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public string LastError
        {
            get { return this._LastError; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._LastError = value;
            }
        }

        private System.String _Errors = System.String.Empty;
        /// <summary>
        /// Gets all errors from the last call of a public member within this class instance.
        /// The Itraceable implementer should only read this property.
        /// This property is set only by the RealtimeTrace layer.
        /// </summary>
        public string Errors
        {
            get { return this._Errors; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._Errors = value;
            }
        }

        #endregion

        private Profile _profile;

        public RootSelectHelper(Profile profile)
        {
            try
            {
                _profile = profile;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, profile); throw; }
        }



        /// <summary>
        /// Returns free space of root.
        /// </summary>
        public DiskSpaceInfo GetSpaceInfo(int root)
        {
            try
            {
                DiskSpaceInfo _newinfo;
                _newinfo.DriveLetter = _profile.Roots[root].RootPath.Substring(0, 1);
                DriveInfo x = new DriveInfo(_newinfo.DriveLetter);
                _newinfo.FreeSpaceAvailable = (ulong)x.AvailableFreeSpace;
                _newinfo.TotalSize = (ulong)x.TotalSize;
                _newinfo.TotalFreeSpace = (ulong)x.TotalFreeSpace;
                return _newinfo;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, root); throw; }
        }

        /// <summary>
        /// Returns free space of all roots.
        /// </summary>
        public DiskSpaceInfo GetSpaceInfo()
        {
            try
            {
                DiskSpaceInfo _newinfo = new DiskSpaceInfo();
                _newinfo.FreeSpaceAvailable = 0;
                _newinfo.TotalFreeSpace = 0;
                _newinfo.TotalSize = 0;
                _newinfo.DriveLetter = "";

                List<string> _counteddrives = new List<string>();
                for (int i = 0; i < _profile.Roots.Count; i++)
                {
                    DiskSpaceInfo _info;
                    _info = GetSpaceInfo(i);
                    if (!_counteddrives.Contains(_info.DriveLetter))
                    {
                        _newinfo.FreeSpaceAvailable += _info.FreeSpaceAvailable;
                        _newinfo.TotalSize += _info.TotalSize;
                        _newinfo.TotalFreeSpace += _info.TotalFreeSpace;
                        _counteddrives.Add(_info.DriveLetter);
                    }
                }
                return _newinfo;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex); throw; }
        }

        // check if filename is on any of the root directories and return the root number or -1 if n/a
        public int GetDirectoryRoot(string filename)
        {
            try
            {
                for (int i = 0; i < _profile.Roots.Count; i++)
                {
                    if (Directory.Exists(_profile.Roots[i].RootPath + filename)) return i;
                }
                return -1;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename); return -1; }
        }

        public int GetFileRoot(string filename)
        {
            try
            {
                for (int i = 0; i < _profile.Roots.Count; i++)
                {
                    if (File.Exists(_profile.Roots[i].RootPath + filename)) return i;
                }

                return -1;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename); return -1; }
        }

        // return full path to first director of file match
        public string GetDirectoryPath(string filename)
        {
            try
            {
                return GetDirectoryPath(filename, GetDirectoryRoot(filename));
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename); throw; }
        }

        public string GetDirectoryPath(string filename, int root)
        {
            try
            {
                if (root < 0) return "";
                else return _profile.Roots[root].RootPath + filename;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename, root); throw; }
        }

        public string GetFilePath(string filename)
        {
            try
            {
                return GetFilePath(filename, GetFileRoot(filename));
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename); throw; }
        }

        public string GetFilePath(string filename, int root)
        {
            try
            {
                if (root < 0) return "";
                return _profile.Roots[root].RootPath + filename;
            }
            catch (Exception ex)
            { TraceFactory.InsertTrace(this, ex, filename, root); throw; }
        }
    }
}